<?php

class Areal_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
    /**
     * Predispatch
     * Checks if the current user identified by role name has rights to the
     * requested url (module/controller/action)
     * If not, it will call denyAccess to be redirected to errorPage
     *
     * @param Zend_Controller_Request_Abstract $request
     * @return void
     **/
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $acl = new Areal_Acl();
        $acl->setConfig(Areal_Config::getInstance()->acl);
        $role_name = Zend_Auth::getInstance()->getIdentity()->getRoleId() ;
        $front = Zend_Controller_Front::getInstance();

        /** Allow error handler in the acl */
        $errorHandler = $front->getPlugin('Zend_Controller_Plugin_ErrorHandler');
        $default_error_module = $errorHandler->getErrorHandlerModule();
        $default_error_controller = $errorHandler->getErrorHandlerController();
        $default_error_action = $errorHandler->getErrorHandlerAction();
        $defaultErrorResource = new Zend_Acl_Resource($default_error_module, $default_error_controller);
        $acl->add( $defaultErrorResource );
        $acl->allow($role_name, $defaultErrorResource->getResourceId());

        /** Check if the given model/controller/action can be dispatched */
        if ( ! $front->getDispatcher()->isDispatchable($request)) {
                $this->_denyAccess(404, 'No such page' );
        } else {
            /** Check if the module/controller/action exists in the acl */
            $resource = new Areal_Acl_Resource($request->getModuleName(),
                                               $request->getControllerName());
            if ( ! $acl->has($resource->getResourceId())) {
                   $this->_denyAccess(404,
                                      'Resource ('
                                      . $resource->getResourceId()
                                      . ') was not found in the Acl');
            } else {    
                /** Check if the module/controller/action can be accessed by the current user */
                if ( ! $acl->isAllowed($role_name, $resource->getResourceId(), $request->getActionName()) &&
                     ! $acl->isAllowed($role_name, $resource->getResourceId()) ) {
                    /** Redirect to access denied page */
                    $this->_denyAccess(403,
                                       'Resource ('
                                       . $resource->getResourceId()
                                       . ') '.$request->getActionName(). ' was denied for '
                                       . $role_name
                                       . ' by the Acl');
                                   //Zend_Debug::dump($acl);
                }
            }
        }

        Zend_Registry::set('Areal_Acl', $acl);
    }

    /**
     * Deny Access Function
     * if role is guest redirects to login, else exception is thrown
     *
     * @param string $role_name
     * @param string|NULL $message
     * @return void
     **/
    protected function _denyAccess($code, $message = 'You are not authorized for access this page.')
    {
            $errorHandler = Zend_Controller_Front::getInstance()->getPlugin('Zend_Controller_Plugin_ErrorHandler');
            $this->getRequest()->setModuleName($errorHandler->getErrorHandlerModule());
            $this->getRequest()->setControllerName($errorHandler->getErrorHandlerController());
            $this->getRequest()->setActionName($errorHandler->getErrorHandlerAction());
            $this->getRequest()->setParam('message', $message);
            $this->getRequest()->setParam('acl_response', $code);
    }
}
